package com.cxf.windex.rest;

import com.cxf.windex.base.msg.ObjectRestResponse;
import com.cxf.windex.base.rest.BaseRestController;
import com.cxf.windex.base.util.CommonUtil;
import com.cxf.windex.base.util.MD5Util;
import com.cxf.windex.biz.AddressBiz;
import com.cxf.windex.biz.JsTechBiz;
import com.cxf.windex.biz.JsUserBiz;
import com.cxf.windex.biz.PayInfoBiz;
import com.cxf.windex.config.MyWxConfig;
import com.cxf.windex.entity.Address;
import com.cxf.windex.entity.JsTech;
import com.cxf.windex.entity.JsUser;
import com.cxf.windex.entity.PayInfo;
import com.cxf.windex.service.WxPayService;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author chenxf
 * @date 3/27/2018
 * @description
 */
@Controller
@RequestMapping("/user/wx")
public class PayController extends BaseRestController<JsUserBiz, JsUser> {

  @Value("${weixin.appid}")
  private String appid;

  @Value("${weixin.appKey}")
  private String appKey;

  @Value("${weixin.mechid}")
  private String mechid;

  @Value("${weixin.notifyUrl}")
  private String notifyUrl;

  @Value("${weixin.fee}")
  private String total_fee;

  @Value("${weixin.totalFee}")
  private String totalFee;

  @Autowired
  private JsTechBiz jsTechBiz;

  @Autowired
  private AddressBiz addresBiz;

  @Autowired
  private PayInfoBiz payInfoBiz;

  @RequestMapping(value = "/price", method = {RequestMethod.GET, RequestMethod.POST})
  @ResponseBody
  public ObjectRestResponse price(
      HttpServletRequest request, HttpServletResponse response) throws Exception {
    Map<String, String> resultMap = new HashMap<String, String>(4);

    resultMap.put("fee", new BigDecimal(total_fee).divide(new BigDecimal("100")).toString());
    resultMap.put("totalFee", new BigDecimal(totalFee).divide(new BigDecimal("100")).toString());
    //resultMap.put("paySign", WxUtil.getMinaSign(appid,timestamp,nonce_str,prepay_id,appKey));
    logger.debug("resultMap={}", resultMap);

    return new ObjectRestResponse().rel(true).msg("生成订单成功")
        .result(resultMap);    //给前端app返回此字符串，再调用前端的微信sdk引起微信支付
  }

  @RequestMapping(value = "/pay", method = {RequestMethod.GET, RequestMethod.POST})
  @ResponseBody
  public ObjectRestResponse orderPay(
      HttpServletRequest request, HttpServletResponse response) throws Exception {
    String userId = this.getCurrentUserId();
    if (userId == null || userId.equals("")) {
      return new ObjectRestResponse().rel(false).msg("用户不存在");
    }
    JsUser user = baseBiz.selectById(userId);
    if (user == null) {
      return new ObjectRestResponse().rel(false).msg("用户不存在");
    }
    //TODO 增加付款前状态判断
    String out_trade_no = CommonUtil.getRandomOrderId(userId);  //777777 需要前端给的参数

    String coupon_id = "7";               //777777

    String attach = userId + "," + coupon_id;
    MyWxConfig config = new MyWxConfig(appid, mechid, appKey);

    String spbill_create_ip = CommonUtil.getClientIp(request);
    //String spbill_create_ip = "10.4.21.78";
    logger.debug("ip={}", spbill_create_ip);
    Map<String, String> result = WxPayService
        .dounifiedOrder(config, attach, out_trade_no, user.getOpenid(), total_fee, spbill_create_ip,
            notifyUrl);
    String nonce_str = (String) result.get("nonce_str");
    String prepay_id = (String) result.get("prepay_id");
    Long time = System.currentTimeMillis() / 1000;
    String timestamp = time.toString();
    if (StringUtils.isBlank(prepay_id)) {
      return new ObjectRestResponse().rel(false).msg("生成订单信息失败");
    }
    JsTech queryEntity = new JsTech();
    queryEntity.setUserid(userId);
    JsTech tech = jsTechBiz.selectOne(queryEntity);
    if (tech != null) {
      JsTech saveEntity = new JsTech();
      saveEntity.setId(tech.getId());
      saveEntity.setUpdUser(out_trade_no);
      saveEntity.setStatus("2");//处理中
      saveEntity.setUpdTime(new Date());
      jsTechBiz.updateSelectiveById(saveEntity);
    }
//插入订单表
    PayInfo payInfo=new PayInfo();
    payInfo.setUserid(tech.getUserid());
    payInfo=payInfoBiz.selectOne(payInfo);
    if(payInfo==null){
      payInfo=new PayInfo();
      payInfo.setName(tech.getTitle());
      payInfo.setAddtime(new Date());
      payInfo.setPayMoney(new BigDecimal(total_fee).divide(new BigDecimal("100")));
      payInfo.setTotalMoney(payInfo.getPayMoney());
      payInfo.setPayCode("certified");
      payInfo.setPayName("认证费");
      payInfo.setUserid(tech.getUserid());
      payInfo.setPayId(tech.getId());
      payInfo.setStatus(0);
      payInfoBiz.insertSelective(payInfo);
    } else {
      payInfo.setName(tech.getTitle());
      payInfo.setAddtime(new Date());
      payInfo.setPayMoney(new BigDecimal(total_fee).divide(new BigDecimal("100")));
      payInfo.setTotalMoney(payInfo.getPayMoney());
      payInfo.setPayCode("certified");
      payInfo.setPayName("认证费");
      payInfoBiz.updateSelectiveById(payInfo);
    }
    Map<String, String> resultMap = new HashMap<String, String>(4);
    resultMap.put("appId", appid);
    resultMap.put("timeStamp", timestamp);
    resultMap.put("nonceStr", nonce_str);
    resultMap.put("package", "prepay_id=" + prepay_id);
    resultMap.put("signType", "MD5");
    resultMap.put("paySign", MD5Util.getSign(resultMap, config));
    //resultMap.put("paySign", WxUtil.getMinaSign(appid,timestamp,nonce_str,prepay_id,appKey));
    logger.debug("resultMap={}", resultMap);

    return new ObjectRestResponse().rel(true).msg("生成订单成功")
        .result(resultMap);    //给前端app返回此字符串，再调用前端的微信sdk引起微信支付

  }

  /**
   * 订单支付异步通知
   */
  @CacheEvict(value="addressList",allEntries=true)
  @ApiOperation(value = "手机订单支付完成后回调")
  @RequestMapping(value = "/notify", method = {RequestMethod.GET, RequestMethod.POST})
  @ResponseBody
  public String WXPayBack(HttpServletRequest request, HttpServletResponse response) {

    String resXml = "";
    logger.debug("进入异步通知");
    try {
      MyWxConfig config = new MyWxConfig(appid, mechid, appKey);
      //
      InputStream is = request.getInputStream();
      //将InputStream转换成String
      BufferedReader reader = new BufferedReader(new InputStreamReader(is));
      StringBuilder sb = new StringBuilder();
      String line = null;
      try {
        while ((line = reader.readLine()) != null) {
          sb.append(line + "\n");
        }
      } catch (IOException e) {
        e.printStackTrace();
      } finally {
        try {
          is.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
      resXml = sb.toString();
      if (StringUtils.isBlank(resXml)) {
        logger.error("手机支付回调通知失败", resXml);
        String result = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
            + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
        return result;
      }
      logger.debug("resultXML={}", resXml);
      Map<String, String> resultMap = WxPayService.payBackMap(resXml, config);
      //设置技师状态

      if (resultMap.get("return_code").equals("SUCCESS")) {
        String out_trade_no = resultMap.get("out_trade_no");

        if (out_trade_no == null || StringUtils.isBlank(out_trade_no)) {
          update(out_trade_no, "-1", resultMap.get("err_code_des"));
        } else {
          if (resultMap.get("total_fee") == null || StringUtils
              .isBlank(resultMap.get("total_fee"))) {
            update(out_trade_no, "-1", "支付金额异常");
          }
          if (!resultMap.get("total_fee").equals(total_fee)) {
            update(out_trade_no, "-1", "支付金额异常 支付金额 ：" + resultMap.get("total_fee"));
          } else {
            update(out_trade_no, "1", "支付成功");
          }
        }
      }
      if (resultMap.get("return_code").equals("FAIL")) {
        update(resultMap.get("out_trade_no"), "-1", resultMap.get("err_code_des"));
      }
      return resultMap.get("xmlBack");
    } catch (Exception e) {
      logger.error("手机支付回调通知失败", e);
      String result = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
          + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
      return result;
    }
  }

  public void update(String out_trade_no, String status, String msg) {
    if (out_trade_no == null || StringUtils.isBlank(out_trade_no)) {
      logger.error("找不到对应技师  订单号={} 错误 ={}", out_trade_no, msg);
    }

    JsTech queryEntity = new JsTech();
    queryEntity.setUpdUser(out_trade_no);
    JsTech tech = jsTechBiz.selectOne(queryEntity);
    if (tech != null) {
      JsTech saveEntity = new JsTech();
      saveEntity.setId(tech.getId());
      switch (status) {
        case "1":
          saveEntity.setStatus("1");
          saveEntity.setPayStatus(msg);
          PayInfo payInfo=new PayInfo();
          payInfo.setUserid(tech.getUserid());
          payInfo=payInfoBiz.selectOne(payInfo);
          if(payInfo==null){
            payInfo=new PayInfo();
            payInfo.setName(tech.getTitle());
            payInfo.setAddtime(new Date());
            payInfo.setPayMoney(new BigDecimal(total_fee).divide(new BigDecimal("100")));
            payInfo.setTotalMoney(payInfo.getPayMoney());
            payInfo.setPayCode("certified");
            payInfo.setStatus(1);
            payInfo.setPayName("认证费");
            payInfo.setUserid(tech.getUserid());
            payInfo.setPayId(tech.getId());
            payInfo.setNotes(tech.getAddress());
            payInfoBiz.insertSelective(payInfo);
          } else {
            payInfo.setName(tech.getTitle());
            payInfo.setStatus(1);
            payInfo.setNotes(tech.getAddress());
            payInfoBiz.updateSelectiveById(payInfo);
          }
          break;
        case "-1":
          saveEntity.setStatus("-1");
          saveEntity.setPayStatus(msg);
          break;
        default:
          saveEntity.setStatus("0");
          saveEntity.setPayStatus(msg);
      }
      jsTechBiz.updateSelectiveById(saveEntity);
      //保存地图信息
      address(tech, true);
      logger.info("技师信息更新成功={}", out_trade_no);
    } else {
      logger.error("找不到对应技师={}", out_trade_no);
    }

  }

  private void address(JsTech entity, boolean isAdd) {
    Address address=addresBiz.selectById(entity.getId());
    if (address==null) {
      addresBiz.insertAddress(new Address(entity));
    } else {
      addresBiz.updateAddressById(new Address(entity));
    }
  }
}
